home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 7
/
BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso
/
Files
/
Util
/
W-Z
/
ZoomIdle 1.1.cpt
/
ZoomIdle.1.1.c
< prev
next >
Wrap
Text File
|
1986-07-29
|
6KB
|
254 lines
/*
ZoomIdle
Version 1.1 25 July 1986
Screen saver desk accessory. Generates successive randomly chosen
rectangles, and zooms each into the next by interpolating a series
of rectangles intermediate in shape and location. Click and hold in
menu bar to pause the display. Click below menu bar to terminate.
The project should include MacTraps and ZoomIdle1.1.c. The project
type should be Desk Accessory.
Changes since 1.0:
Works with Macintosh XL (wider screen).
Doesn't clear the menu bar until the window receives an activate
event. 1.0 cleared the bar immediately, which was too early -
some programs would crash when ZoomIdle exited.
Paul DuBois
Wisconsin Regional Primate Research Center
1220 Capitol Court
University of Wisconsin-Madison
Madison, WI 53706
UUCP: {allegra, ihnp4, seismo}!uwvax!uwmacc!dubois
ARPA: dubois@easter
dubois@unix.macc.wisc.edu
*/
# include <DeviceMgr.h>
# include <WindowMgr.h> /* includes QuickDraw.h, MacTypes.h */
# include <EventMgr.h>
# include <MenuMgr.h>
# define nil 0L
/*
zoomSteps controls the number of rectangles that are drawn in each
interpolative series. zoomShow controls how many rectangles are
visible at once. These two values may be varied independently, but
they must both be greater than zero.
*/
# define zoomSteps 15
# define zoomShow 15
/* global variables */
Rect zRect[zoomShow];
int zIndex;
/*
Return integer between zero and max (inclusive). Assumes max is
non-negative.
*/
Rand (max)
int max;
{
register int t;
if ((t = Random ()) < 0) t = -t;
return (t % (max + 1));
}
/*
Interpolate one rectangle smoothly into another. This algorithm
assumes that it is erasing the previous series while it's
drawing the new one. The first time this is called, that is not
true, which is why the init code sets all the zRect rectangles
empty - it's harmless to erase empty rectangles (doesn't show on
screen).
Pen mode should be set to patXor, so that the first drawing shows
the rectangle, the second time erases it. Gray seems to work
best for the pen pattern: white is too stark a contrast, except
perhaps for the very dialectic.
*/
ZoomRect (r1, r2)
Rect r1, r2;
{
register int r1left, r1top;
register int l, t;
register int j;
int hDiff, vDiff, widDiff, htDiff;
int r, b;
int rWid, rHt;
register Rect *rp;
r1left = r1.left;
r1top = r1.top;
hDiff = r2.left - r1left; /* positive if moving to right */
vDiff = r2.top - r1top; /* positive if moving down */
rWid = r1.right - r1left;
rHt = r1.bottom - r1top;
widDiff = (r2.right - r2.left) - rWid;
htDiff = (r2.bottom - r2.top) - rHt;
/*
order of evaluation is important in the rect coordinate calculations.
since all arithmetic is integer, you can't save time by calculating
j/zoomSteps and using that - it'll usually be zero.
*/
for (j = 1; j <= zoomSteps; j++)
{
if (++zIndex >= zoomShow)
zIndex = 0;
rp = &zRect[zIndex];
FrameRect (rp); /* erase a rectangle */
l = r1left + (hDiff * j) / zoomSteps;
t = r1top + (vDiff * j) / zoomSteps;
r = l + rWid + (widDiff * j) / zoomSteps;
b = t + rHt + (htDiff * j) / zoomSteps;
SetRect (rp, l, t, r, b);
FrameRect (rp);
}
}
main(p, d, n)
cntrlParam *p; /* ==> parameter block */
DCtlPtr d; /* ==> device control entry */
int n; /* entry point selector */
{
register DCtlPtr dce = d;
Rect dstRect;
Point pt1, pt2;
long pat[2];
static int scrnSizeX;
static int scrnSizeY;
static Rect srcRect;
static Handle theMenuBar;
static WindowPtr theWind;
static Boolean zoomAway = false;
/* check to make sure our data area was allocated */
if (dce->dCtlStorage == 0)
{
if (n == 0) /* open */
CloseDriver(dce->dCtlRefNum);
}
else switch (n) /* dispatch */
{
case 0: /* open */
dce->dCtlFlags |= dNeedLock | dNeedTime;
dce->dCtlDelay = 0;
dce->dCtlEMask = everyEvent;
GetWMgrPort (&theWind);
srcRect = theWind->portRect;
scrnSizeX = srcRect.right; /* get size of screen */
scrnSizeY = srcRect.bottom;
theWind = NewWindow (nil, &srcRect, "\p", true,
noGrowDocProc, -1L, true, 0L);
RectRgn (theWind->visRgn, &srcRect);
((WindowPeek) theWind)->windowKind = dce->dCtlRefNum;
/*
Initialize the rect array. This also sets zIndex
to a value that causes it to reset to zero on the
first call to ZoomRect.
*/
for (zIndex = 0; zIndex < zoomShow; ++zIndex)
SetRect (&zRect[zIndex], 0, 0, 0, 0);
break;
case 2: /* control */
SetPort (theWind);
switch (p->csCode)
{
case accEvent: /* put glasses on to read next switch */
switch (((EventRecord *) * (long *) &p->csParam)->what)
{
case activateEvt:
theMenuBar = GetMenuBar ();
ClearMenuBar ();
PaintRect (&srcRect /* = &theWind->portRect */);
PenMode (patXor); /* do all drawing in xor */
pat[0] = pat[1] = 0xaa55aa55L;
PenPat (&pat); /* can't use QD global pats! */
zoomAway = true;
break;
case mouseDown: /* quit on mousedown event */
CloseDriver(dce->dCtlRefNum);
break;
}
break;
case accRun:
if (zoomAway) /* activated */
{
ObscureCursor (); /* keep cursor hidden */
pt1.h = Rand (scrnSizeX); /* generate rect and zoom to it */
pt1.v = Rand (scrnSizeY);
pt2.h = Rand (scrnSizeX);
pt2.v = Rand (scrnSizeY);
Pt2Rect (pt1, pt2, &dstRect);
ZoomRect (srcRect, dstRect);
srcRect = dstRect;
}
break;
}
break;
case 4: /* close */
DisposeWindow (theWind);
SetMenuBar (theMenuBar); /* restore menu bar */
DisposHandle (theMenuBar);
DrawMenuBar ();
break;
}
/* done */
return(0);
}
--- end ---